﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace game
{
    public class FlyUpMovement
    {
        public float PitchSpeed { get; set; }
        public float HoverSpeed { get; set; }
        public float LeanStablePointEpsilon { get; set; }

        public float OldLayerHeight { get; private set; }
        public float NewLayerHeight { get; private set; }

        private float distY;
        private float movedY;

        private float snapToLayerOffset = 20.0f;

        private bool hovering;
        private float pitchStopPoint = 0.55f; // radians

        public bool Finished { get; private set; }

        private enum State
        {
            BEGIN_PITCH,
            HOVER,
            END_PITCH,
        }

        private State state;

        public FlyUpMovement()
        {
            PitchSpeed = 0.0008f;
            HoverSpeed = 100.0f;
            LeanStablePointEpsilon = 0.05f;
        }

        public void Start(float oldLayerHeight, float newLayerHeight)
        {
            this.OldLayerHeight = oldLayerHeight;
            this.NewLayerHeight = newLayerHeight;
            Finished = false;
            hovering = true;
            state = State.BEGIN_PITCH;
            distY = newLayerHeight - oldLayerHeight;
            movedY = 0;
        }

        public void RotateXAndHover(ref float curRot, ref Vector3 curPos)
        {
            float hoverMove = 0.0f;
            switch (state)
            {
                case State.BEGIN_PITCH:
                    curRot += 0.8f * PitchSpeed * MovementControl.DeltaTimeMs;
                    if (curRot > pitchStopPoint)
                    {
                        state = State.HOVER;
                    }
                    hoverMove = curRot * curRot * HoverSpeed * MovementControl.DeltaTimeMs;

                    break;

                case State.HOVER:
                    hoverMove = pitchStopPoint * pitchStopPoint * HoverSpeed * MovementControl.DeltaTimeMs;
                    if (movedY > distY * 0.8f)
                    {
                        state = State.END_PITCH;
                    }
                    break;

                case State.END_PITCH:
                    if (Math.Abs(curRot) < LeanStablePointEpsilon)
                    {
                        curRot = 0.0f;
                        hoverMove = 10.0f;

                        if (!hovering)
                            Finished = true;
                    }
                    else
                    {
                        curRot -= PitchSpeed * MovementControl.DeltaTimeMs;
                        if (hovering)
                        {
                            hoverMove = curRot * curRot * HoverSpeed * MovementControl.DeltaTimeMs;
                        }
                    }

                    if ((distY - movedY) < snapToLayerOffset && hovering)
                    {
                        curPos.Y = NewLayerHeight;
                        hoverMove = 0.0f;
                        hovering = false;

                        if (curRot == 0.0f)
                            Finished = true;
                    }
                    break;
            }

            curPos.Y += hoverMove;
            movedY += hoverMove;
        }
    }
}
